// Global variables
/* ID of the tagcloud element */
var TAGCLOUD = "tagcloud";

var SELECTED_TAG = "___selected";

var MAX_SIZE = 5;

var MIN_FONT_SIZE = 1;
var MAX_FONT_SIZE = 5;
/* hash containing tags to files element list */
var tagsHash = new Hash();

/*
 * Internet Timestamp Parser Copyright (c) 2009 Sebastiaan Deckers License: GNU
 * General Public License version 3 or later
 */
Date.prototype.setISO8601 = function(timestamp) {
	var match = timestamp
			.match("^([-+]?)(\\d{4,})(?:-?(\\d{2})(?:-?(\\d{2})"
					+ "(?:[Tt ](\\d{2})(?::?(\\d{2})(?::?(\\d{2})(?:\\.(\\d{1,3})(?:\\d+)?)?)?)?"
					+ "(?:[Zz]|(?:([-+])(\\d{2})(?::?(\\d{2}))?)?)?)?)?)?$");
	if (match) {
		for ( var ints = [ 2, 3, 4, 5, 6, 7, 8, 10, 11 ], i = ints.length - 1; i >= 0; --i)
			match[ints[i]] = (typeof match[ints[i]] != "undefined" && match[ints[i]].length > 0) ? parseInt(
					match[ints[i]], 10)
					: 0;
		if (match[1] == '-') // BC/AD
			match[2] *= -1;
		var ms = Date.UTC(match[2], // Y
				match[3] - 1, // M
				match[4], // D
				match[5], // h
				match[6], // m
				match[7], // s
				match[8] // ms
				);
		if (typeof match[9] != "undefined" && match[9].length > 0) // offset
			ms += (match[9] == '+' ? -1 : 1)
					* (match[10] * 3600 * 1000 + match[11] * 60 * 1000); // oh
		// om
		if (match[2] >= 0 && match[2] <= 99) // 1-99 AD
			ms -= 59958144000000;
		this.setTime(ms);
		return this;
	} else
		return null;
}

// prototype event handlers

document.observe("dom:loaded", function() {
	// load tag infos
		loadTagInfos();
		// load timeline
		loadTimeline();
		// Load control tabs
		new Control.Tabs('navigation_tabs', {
			activeClassName : "controlTabActive"
		});
	});

function selectNearestAncestor(element, selector) {
	var ancestors = element.ancestors();
	return ancestors.find(function(node) {
		return node.select(selector).size() > 0;
	});
}

/*-------------------------------------- timeline functions -------------------------------------*/
function loadTimeline() {
	var events = loadTimelineData();
	var eventSource = new Timeline.DefaultEventSource();
	var eventsArray = new Array();
	for(var i=0; i<events.size(); i++) {
		var evt = new Timeline.DefaultEventSource.Event( {
			start : events[i][0],
			instant : true,
			text : events[i][1],
			link : events[i][2]
		});
		eventsArray.push(evt);
    }
	eventSource.addMany(eventsArray);

	var bandInfos = [ Timeline.createBandInfo( {
		width : "70%",
		intervalUnit : Timeline.DateTime.MONTH,
		intervalPixels : 100
	}), Timeline.createBandInfo( {
		width : "30%",
		intervalUnit : Timeline.DateTime.YEAR,
		intervalPixels : 200
	}) ];
	// synchronize scrolling
	bandInfos[1].syncWith = 0;
	bandInfos[1].highlight = true;

	// create timeline
	tl = Timeline.create($("timeline"), bandInfos);
}

function loadTimelineData() {
	return [
	        	[new Date(2010, 01,01), "A", "http://www.google.fr"],
	        	[new Date(2010, 02,01), "B", "http://www.google.fr"],
	        	[new Date(2010, 02,10), "C", "http://www.google.fr"],
	        ];
}
/*
function loadTimelineData() {
	var dates = $$("span.date span.data");
	var events = dates.inject(new Array(), function(acc, element) {
		var a = acc[acc.size()] = new Array();
		var aLink = selectNearestAncestor(element, "a").select("a")[0];
		a[0] = (new Date()).setISO8601(a[0]);
		a[1] = aLink.innerText;
		a[2] = aLink.getAttribute("href");
		return acc;
	});
	return events;
}*/

/*-------------------------------------- tag cloud functions -------------------------------------*/
function clickTagSpan(event) {
	switchCloud(this.innerText);
}

function loadTagInfos() {
	var filesList = $$("div.content");
	if (filesList == undefined) {
	} else {
		loadTagCloud(event);
		// After having loaded tag cloud, check if there are tags in url, then
		// select them
		loadUrlTags();
		// Add tag handling on span elements
		$$("span.tag").each(function(element) {
			Event.observe(element, 'click', clickTagSpan);
		});
	}
}

function loadUrlTags() {
	var url = window.location.href;
	if (url.indexOf("?") > 0) {
		var params = url.substring(url.indexOf("?") + 1);
		var tags = params.toQueryParams()["tags"].split("+");
		tags.each(function(tagName) {
			switchTagSelection(tagName);
		});
		refreshFiles();
	}
}

/**
 * Generates a tag cloud from the file list. in fact, it will generate from the
 * input file list an output tag list, reversing the order of the input tag list
 */
function loadTagCloud(event) {
	tagsHash.keys().clear();
	var maxFiles = 0;
	var filesList = $$("ul.files li");
	var index = 0;
	filesList.each(function(element) {
		element.id = "file_" + (++index);
		element.descendants().each(function(node) {
			if (node.match(".tag")) {
				var tag = node.innerText;
				if (tagsHash.keys().indexOf(tag) < 0) {
					tagsHash.set(tag, new Array());
				}
				tagsHash.get(tag).push(element.id);
				maxFiles = Math.max(maxFiles, tagsHash.get(tag).size());
			}
		});
	});
	// Now we have our tags, let's create the div containing all
	var list = $$("ul.files");
	// Check if list exists
	if (list != null && list.first() != null) {
		var tagcloud = $(TAGCLOUD);
		tagsHash.keys().sort().each(
				function(tagName) {
					var size = tagsHash.get(tagName).size();
					var weight = (Math.log(size) - Math.log(1))
							/ (Math.log(maxFiles) - Math.log(1));
					var fontSizeOfCurrentTag = MIN_FONT_SIZE
							+ Math.round((MAX_FONT_SIZE - MIN_FONT_SIZE)
									* weight);
					tagcloud.insert( {
						bottom : "<span id=\"" + tagName
								+ "\" class='tagName' onclick=\"switchCloud('"
								+ tagName + "')\"><font size=\""
								+ fontSizeOfCurrentTag + "\">" + tagName
								+ "</font></span> "
					});
				});
		tagcloud
				.insert( {
					bottom : "<div id='clear'><a href='#tagcloud' onClick='clearTagCloud()'>Clear tag cloud</a></div>"
				});
	}
}

function switchTagSelection(tagName) {
	var element = $(tagName);
	if (element.hasClassName(SELECTED_TAG)) {
		element.removeClassName(SELECTED_TAG);
	} else {
		element.addClassName(SELECTED_TAG);
	}
}

function switchCloud(tagName) {
	switchTagSelection(tagName);
	refreshFiles();
}

function clearTagCloud() {
	var tagelements = $$("#" + TAGCLOUD + " .tagName");
	var tags = new Array();
	tagelements.each(function(element) {
		if (element.hasClassName(SELECTED_TAG)) {
			switchTagSelection(element.id);
		}
	});
	refreshFiles();
}

/**
 * Refresh files according to selected tags. First, grab selected tags list
 */
function refreshFiles() {
	var tagelements = $$("#" + TAGCLOUD + " .");
	var tags = new Array();
	tagelements.each(function(element) {
		if (element.hasClassName(SELECTED_TAG)) {
			tags.push(element.id);
			// opera.postError("selected tags contains "+element.innerText);
		}
	});
	// Now the tag list is constructed, process files elements
	var potential = $$("ul.files li");
	var matching = potential;
	// opera.postError("tagsHash is made of "+tagsHash.size()+" elements");
	tags.each(function(tagName) {
		var current = tagsHash.get(tagName);
		// opera.postError(tagName+" has "+current.size()+" associated
			// entries");
			matching = matching.findAll(function(element, index) {
				var returned = current.indexOf(element.id) >= 0;
				return returned;
			});
		});
	// Create a pure id collection
	matching = matching.collect(function(element, index) {
		return element.id;
	});
	// opera.postError("found "+matching.size()+" elements from
	// "+potential.size()+" existing ones");
	potential.each(function(element) {
		// Special handling for empty tag names collection to allow a reset
			if (tags.size() > 0 && matching.indexOf(element.id) < 0) {
				// opera.postError("hiding \""+element.innerText+"\"");
				element.removeClassName("visible");
				element.addClassName("hidden");
			} else {
				element.removeClassName("hidden");
				element.addClassName("visible");
			}
		});
}